﻿using Eps.Ai.Common;
using InfonavaEye.util;
using Newtonsoft.Json.Linq;
using Sylan.Common.Util;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InfonavaEye.handler
{
    /// <summary>
    /// 光源处理器
    /// 对应型号：TSD-DPA20024V-2HP
    /// </summary>
    public class LightHandler
    {
        //private UpperComputerUtil upper;

        private SerialPort SP_ReadData = null;

        public Action LightConnectedDelegate;

        //心跳监测
        private bool heartBeatEnabled = false;
        System.Timers.Timer heartBeatTimer = null;
        public event Action<bool> heartBeatDelegate;

        bool isConnected = false;
        int channelNo = Config.LIGHT_SOURCE_CHANNEL;

        private static readonly LightHandler instance = new LightHandler();

        static LightHandler() { }
        private LightHandler() { }
        public static LightHandler Instance
        {
            get
            {
                return instance;
            }
        }

        public void Start()
        {
            if (isConnected)
            {
                if (this.LightConnectedDelegate != null)
                {
                    this.LightConnectedDelegate.Invoke();
                }
                return;
            }

            ThreadHelper.ExcuteThreadTask(() =>
            {
                Connect();
            }, 50);
        }

        public void Close()
        {
            try
            {
                if (SP_ReadData != null)
                {
                    SP_ReadData.Close();
                    isConnected = false;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("关闭光源串口时发生异常:" + e.StackTrace);
            }
        }

        private void Connect(Action complete = null)
        {
            if (SP_ReadData != null && SP_ReadData.IsOpen) return;

            ThreadHelper.ExcuteThreadTask(() =>
            {
                try
                {
                    SP_ReadData = new SerialPort();
                    SP_ReadData.PortName = Config.LIGHT_SOURCE_COM;
                    SP_ReadData.BaudRate = 9600;
                    SP_ReadData.DataBits = 8;
                    SP_ReadData.StopBits = System.IO.Ports.StopBits.One;
                    SP_ReadData.Parity = System.IO.Ports.Parity.None;
                    SP_ReadData.DataReceived += SP_ReadData_DataReceived;
                    SP_ReadData.Close();
                    SP_ReadData.Open();

                    isConnected = true;
                    Console.WriteLine("光源已连接");
                    //打开1通道
                    OpenChannel();
                    InitTimer();
                    if (this.LightConnectedDelegate != null)
                    {
                        this.LightConnectedDelegate.Invoke();
                    }
                }

                catch (Exception ex)
                {
                    Console.WriteLine("连接光源连接异常,{0} {1}", ex.Message, ex.StackTrace);
                    Logger.Write(Level.ERROR, "连接光源异常", ex);

                    isConnected = false;
                    Console.WriteLine("光源连接失败，再次尝试重连");
                    ThreadHelper.Sleep(500);
                    //再次重新连接PLC
                    Connect(complete);
                }
            });
        }

        private void SP_ReadData_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // 接收数据
            byte[] buffer = null;
            byte[] data = new byte[2048];
            int receiveCount = 0;
            while (true)
            {
                System.Threading.Thread.Sleep(20);
                if (SP_ReadData.BytesToRead < 1)
                {
                    buffer = new byte[receiveCount];
                    Array.Copy(data, 0, buffer, 0, receiveCount);
                    break;
                }

                receiveCount += SP_ReadData.Read(data, receiveCount, SP_ReadData.BytesToRead);
            }

            if (receiveCount == 0) return;
            string msg = string.Empty;
            msg = Encoding.ASCII.GetString(buffer);
            Console.WriteLine("光源串口收到数据：" + msg);
        }

        /// <summary>
        /// 连接通道
        /// </summary>
        public void OpenChannel() {
            string fullChannelCmd = String.Format("$1{0}000", channelNo);
            SendString(AppendXOR(fullChannelCmd));
            /*JObject stopJobject = upper.ReadResultsString(AppendXOR(fullChannelCmd), 8);
            if (stopJobject.GetValue("Code").ToString().Equals("500"))
            {
                Console.WriteLine("光源-打开通道失败，返回：{0}", stopJobject.GetValue("msg"));
            }
            else {
                Console.WriteLine("光源-打开通道成功");
            }*/
        }

        /// <summary>
        /// 发送字符
        /// </summary>
        private void SendString(string text) {
            try
            {
                byte[] send = Encoding.ASCII.GetBytes(text);
                Console.WriteLine("光源-发送数据:{0}", Encoding.ASCII.GetString(send));
                SP_ReadData?.Write(send, 0, send.Length);
            }
            catch (Exception ex) {
                Console.WriteLine("光源-发送数据失败，{0}，{1}", ex.Message,ex.StackTrace);
            }
        }

        /// <summary>
        /// 改变亮度
        /// </summary>
        /// <param name="luminanceNum">0~255 ascii码</param>
        public void ChangeLuminance(int luminanceNum) {
            Console.WriteLine("改变亮度值为：{0}", luminanceNum);
            //转换为16进制
            string hexStr = luminanceNum.ToString("X3");
            string fullChannelCmd = String.Format("$3{0}{1}", channelNo, hexStr);
            string fullCmd = AppendXOR(fullChannelCmd);
            Console.WriteLine("改变亮度,完整命令为：{0}", fullCmd);
            SendString(fullCmd);
            /*JObject stopJobject = upper.ReadResultsString(fullCmd, 8);
            if (stopJobject.GetValue("Code").ToString().Equals("500"))
            {
                Console.WriteLine("光源-改变亮度失败，返回：{0}", stopJobject.GetValue("msg"));
            }
            else
            {
                Console.WriteLine("光源-改变亮度成功");
            }*/
        }

        /// <summary>
        /// 在指令末尾添加异或和检验位
        /// </summary>
        /// <returns></returns>
        private string AppendXOR(string command) {

            char[] cmdStrs = command.ToArray();

            //字符转换为ascii码
            System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
            byte[] asciiBytes = asciiEncoding.GetBytes(command);
            //转换为16进制
            //string hexStr = intAsciiCode.ToString("X2");
            ushort[] hexBytes = new ushort[asciiBytes.Length];
            for (int i = 0; i < asciiBytes.Length; i++)
            {
                hexBytes[i] = (ushort)int.Parse(string.Format("{0:X2} ", asciiBytes[i]));
            }

            byte[] highArray = new byte[asciiBytes.Length];
            byte[] lowArray = new byte[asciiBytes.Length];
            for (int i = 0; i < hexBytes.Length; i++)
            {
                ushort hex = hexBytes[i];
                highArray[i] = ByteArrayConvert.ToBIN(hex / 10);//得到16进制的高位
                lowArray[i] = ByteArrayConvert.ToBIN(hex % 10);//得到16进制的低位
            }
            string highStr = ByteArrayConvert.calcXORSum(highArray);
            string lowStr = ByteArrayConvert.calcXORSum(lowArray);
           /* Console.WriteLine(ByteArrayConvert.calcXORSum(highArray));
            Console.WriteLine("---------------");
            Console.WriteLine(ByteArrayConvert.calcXORSum(lowArray));*/
            return command+ highStr+lowStr;
        }

        /// <summary>
        /// 检验电源是否连通
        /// </summary>
        /// <returns></returns>
        private bool CheckLight()
        {
            //获取亮度值
            SendString(AppendXOR("$41000"));
            return true;
            /*JObject stopJobject = upper.ReadResultsString("$4100012",8);

            if (stopJobject == null)
                return false;
            if (stopJobject.GetValue("Code").ToString().Equals("500"))
            {
                return false;
            }
            return true;*/
        }

        private void InitTimer()
        {
            heartBeatTimer = new System.Timers.Timer(Config.PLC_HEARTBEAT_INTEVAL);
            heartBeatTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerHeartBeat);
            heartBeatTimer.AutoReset = true;
            heartBeatTimer.Enabled = false;
            heartBeatTimer.Stop();
        }

        /// <summary>
        /// 开启心跳
        /// </summary>监测
        public void WatchHeartBeat()
        {
            heartBeatEnabled = true;
            heartBeatTimer.Enabled = true;
            heartBeatTimer.Start();
        }

        public void UnWatchHeartBeat()
        {
            heartBeatEnabled = false;
            heartBeatTimer.Stop();
            heartBeatTimer.Enabled = false;
        }

        /// <summary>
        /// 光源-心跳监测
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void OnTimerHeartBeat(object source, System.Timers.ElapsedEventArgs e)
        {
            if (!heartBeatEnabled) return;
            var isOK = CheckLight();
            Console.WriteLine("光源心跳监测:" + isOK);
            if (heartBeatDelegate != null)
            {
                heartBeatDelegate.Invoke(isOK);
            }
        }
    }
}
